package com.luhuiguo.cms.server.service.impl;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;

import org.springframework.beans.BeanUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.luhuiguo.cms.server.entity.User;
import com.luhuiguo.cms.server.service.UserService;
import com.luhuiguo.cms.server.util.SecurityUtils;

@Service("userService")
// @Transactional
public class UserServiceImpl implements UserService {

    @PersistenceUnit
    private EntityManagerFactory emf;

    // @PersistenceContext
    // private EntityManager em;

    @SuppressWarnings("unchecked")
    @Override
    public List<User> findUsers() {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT t FROM User t");
            List<User> list = q.getResultList();
            list.size();
            return list;
        } finally {
            em.close();
        }

    }

    @Override
    public User getUser(Long id) {
        EntityManager em = emf.createEntityManager();
        try {
            return em.find(User.class, id);
        } finally {
            em.close();
        }

    }

    @SuppressWarnings("unchecked")
    @Override
    public User getUserByUsername(String username) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT t FROM User t WHERE t.username=:username");
            q.setParameter("username", username);
            List<User> list = q.getResultList();
            if (list.size() > 0) {
                return list.get(0);
            } else {
                return null;
            }
        } finally {
            em.close();
        }

    }

    @SuppressWarnings("unchecked")
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT t FROM User t WHERE t.username=:username");
            q.setParameter("username", username);
            List<User> list = q.getResultList();
            if (list.size() > 0) {
                return list.get(0);
            } else {
                throw new UsernameNotFoundException("Username not found: " + username);
            }
        } finally {
            em.close();
        }

    }

    @Override
    public void deleteUser(Long id) {
        EntityManager em = emf.createEntityManager();
        try {
            em.remove(em.find(User.class, id));
        } finally {
            em.close();
        }

    }

    @Override
    public void saveUser(User user) {

        EntityManager em = emf.createEntityManager();
        try {
            String username = user.getUsername();
            Query q = em.createQuery("SELECT t FROM User t WHERE t.username=:username");
            q.setParameter("username", username);
            List<?> list = q.getResultList();
            if (list.size() > 0) {
                throw new DataIntegrityViolationException("Username already exists: " + username);
            }
            user.setCreated(new Date());
            user.setCreatedBy(SecurityUtils.getCurrentUsername());
            user.setLastModified(user.getCreated());
            user.setLastModifiedBy(user.getCreatedBy());
            em.persist(user);
        } finally {
            em.close();
        }

    }

    @Override
    public User updateUser(User user) {
        EntityManager em = emf.createEntityManager();
        try {
            User u = em.find(User.class, user.getId());
            if (null == u) {
                throw new DataRetrievalFailureException("UserId not found: " + user.getId());
            }
            BeanUtils.copyProperties(user, u, new String[]{ "id", "username", "created", "createdBy" });
            u.setLastModified(new Date());
            u.setLastModifiedBy(SecurityUtils.getCurrentUsername());
            return em.merge(u);
        } finally {
            em.close();
        }

    }

}
